
/**
 * 计算最佳线程数的配置选项
 * @param {string} taskType - 任务类型：'cpu'(CPU密集型) 或 'io'(IO密集型)
 * @param {number} [cpuCount] - CPU核心数，默认使用navigator.hardwareConcurrency或4
 * @param {number} [blockingCoefficient] - 阻塞系数，仅对IO密集型任务有效，范围0~1，默认0.8
 * @param {string} [environment] - 运行环境：'development'(开发环境) 或 'production'(生产环境)，
 *                                 默认为从import.meta.env获取，若无法获取则必须提供
 */
export interface OptimalThreadCountOptions {
  /** 任务类型：'cpu'(CPU密集型) 或 'io'(IO密集型) */
  taskType: 'cpu' | 'io';
  /** CPU核心数，默认使用navigator.hardwareConcurrency或4 */
  cpuCount?: number;
  /** 阻塞系数，仅对IO密集型任务有效，范围0~1，默认0.8 */
  blockingCoefficient?: number;
  /** 运行环境：'development'(开发环境) 或 'production'(生产环境)，
   * 默认为从import.meta.env获取，若无法获取则必须提供
   */
  environment?: 'development' | 'production';
}


/**
 * 解析时间格式，将不同格式的时间转换为毫秒数
 * @param {number | string | undefined} duration - 时间值，可以是数字（毫秒）或字符串（如'0.5s'、'500ms'）
 * @param {number} [defaultValue=500] - 当时间值无效时返回的默认值（毫秒）
 * @returns {number} 转换后的毫秒数
 * @example
 * // 数字格式（毫秒）
 * parseDuration(500); // 500
 * // 字符串格式（秒）
 * parseDuration('0.5s'); // 500
 * // 字符串格式（毫秒）
 * parseDuration('500ms'); // 500
 * // 无效格式，返回默认值
 * parseDuration('invalid'); // 500
 */
export function parseDuration(
  duration: number | string | undefined,
  defaultValue: number = 500
): number {
  // 如果没有提供时间值，返回默认值
  if (!duration) return defaultValue;
  
  // 如果已经是数字类型，直接返回
  if (typeof duration === 'number') return duration;
  
  // 处理字符串格式的时间
  const match = duration.match(/^(\d+(?:\.\d+)?)([ms])$/);
  if (match) {
    const value = parseFloat(match[1]);
    const unit = match[2];
    // 转换为毫秒
    return unit === 's' ? value * 1000 : value;
  }
  
  // 默认返回指定的默认值
  return defaultValue;
}

/**
 * 根据任务类型和运行环境计算最佳线程数
 * 
 * @description
 * 不同类型的任务和运行环境需要不同的线程数配置以获得最佳性能：
 * - **CPU密集型任务(cpu)**: 主要消耗CPU资源，如复杂计算、数据处理、图像处理等。
 *   这类任务很少被阻塞，CPU利用率高，最佳线程数接近CPU核心数。
 * - **IO密集型任务(io)**: 主要等待IO操作完成，如网络请求、文件读写、数据库操作等。
 *   这类任务大部分时间处于等待状态，CPU利用率低，可以使用更多线程来充分利用CPU资源。
 * - **开发环境(development)**: 当前后端运行在同一台电脑上时，为避免前端占用全部CPU资源，
 *   线程数会在计算结果的基础上减半，确保后端也能获得足够的资源。
 * - **生产环境(production)**: 使用完整计算结果，最大化前端性能。
 * 
 * 环境类型优先级：
 * 1. 优先从Vite环境变量import.meta.env获取(NODE_ENV或MODE)
 * 2. 其次使用用户提供的environment参数
 * 3. 若以上均无法获取，则抛出异常
 * 
 * @param {OptimalThreadCountOptions} options - 配置选项
 * @param options.taskType - 任务类型
 * @param options.cpuCount - CPU核心数
 * @param options.blockingCoefficient - 阻塞系数
 * @param options.environment - 运行环境
 * @returns {number} 最佳线程数
 * @throws {Error} 当无法确定运行环境时抛出异常
 * @example
 * // 从Vite环境变量获取环境类型的CPU密集型任务
 * const cpuThreads = getOptimalThreadCount({ taskType: 'cpu' });
 * @example
 * // 手动指定环境类型的IO密集型任务
 * const ioThreads = getOptimalThreadCount({
 *   taskType: 'io',
 *   environment: 'production'
 * });
 * @example
 * // 自定义CPU核心数、阻塞系数和环境
 * const customThreads = getOptimalThreadCount({
 *   taskType: 'io',
 *   cpuCount: 8,
 *   blockingCoefficient: 0.9,
 *   environment: 'development'
 * });
 */
export function getOptimalThreadCount(options: OptimalThreadCountOptions): number {
  const {
    taskType,
    cpuCount = navigator.hardwareConcurrency || 4,
    blockingCoefficient = 0.8,
    environment: userEnvironment
  } = options;
  
  // 尝试从Vite环境变量获取环境类型
  let envFromVite: 'development' | 'production' | undefined;
  if (typeof import.meta !== 'undefined' && import.meta.env) {
    const nodeEnv = import.meta.env.NODE_ENV;
    const mode = import.meta.env.MODE;
    
    if (nodeEnv === 'development' || nodeEnv === 'production') {
      envFromVite = nodeEnv;
    } else if (mode === 'development' || mode === 'production') {
      envFromVite = mode;
    }
  }
  
  // 确定最终环境类型
  const environment = envFromVite || userEnvironment;
  
  // 如果无法确定环境类型，抛出异常
  if (!environment) {
    throw new Error('无法确定运行环境，请提供environment参数或确保Vite环境变量NODE_ENV/MODE可用');
  }
  
  // 确保阻塞系数在有效范围内
  const safeBlockingCoefficient = Math.max(0, Math.min(1, blockingCoefficient));
  
  let threadCount: number;
  
  if (taskType === 'cpu') {
    // CPU密集型任务: 核心数 + 1
    threadCount = cpuCount + 1;
  } else {
    // IO密集型任务: 核心数 / (1 - 阻塞系数)
    // 阻塞系数通常在0.8~0.9之间
    threadCount = Math.ceil(cpuCount / (1 - safeBlockingCoefficient));
  }
  
  // 开发环境下减半线程数
  if (environment === 'development') {
    threadCount = Math.max(1, Math.floor(threadCount / 2));
  }
  
  // 限制线程数在1~16之间
  return Math.max(1, Math.min(16, threadCount));
}